package u1;

import static java.lang.System.*;
import static u1.Util.*;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

/**
 * For any link to a redirect, change the link so that it redirects to the final
 * destination node. (If there are any redirects that redirect to redirects, it
 * will put out a warning, but it won't find the final destination.) Then remove
 * all of the redirects. You will need a fairly large amount of memory to do
 * this.
 * 
 * Takes the adjacency list on standard in. Takes the name of a file containing
 * a list of redirect node numbers and the nodes they redirect to, delimited by
 * whitespace, that tell the follower what nodes are redirect nodes (see
 * u1.ForwardLinks; this is the .redirect file). Produces the resulting
 * adjacency list on standard out, one node number per line.
 */
public class FollowRedirects {
  public static void main(String[] args) throws FileNotFoundException {
    if (args.length != 1) {
      err.println("See comments for usage.");
      exit(-1);
    }

    String redirectFile = args[0];

    /*
     * Scan redirect nodes.
     */
    trace("Reading redirects from %s...", redirectFile);
    Scanner redirectScanner = new Scanner(new File(redirectFile));
    Map<Integer, Integer> redirects = new HashMap<Integer, Integer>();
    while (redirectScanner.hasNextInt()) {
      int redirectSource = redirectScanner.nextInt();
      if (!redirectScanner.hasNextInt()) {
        err.println(String.format("Unpaired redirect source %d.",
            redirectSource));
        exit(-1);
      }
      int redirectTarget = redirectScanner.nextInt();
      redirects.put(redirectSource, redirectTarget);
    }
    redirectScanner.close();
    trace("Got %d redirects.", redirects.size());

    /*
     * We need to get the whole adjacency list in memory (or we could do two
     * passes, but that might be slower on the Eureka nodes.)
     */
    Map<Integer, Set<Integer>> adj = AdjReader.loadT(in, PAGES_MAX);
    trace("Loaded %d nodes from stdin.", adj.size());

    /*
     * Remove redirect pages from adjacency list (will do links next).
     */
    for (Integer redirect : redirects.keySet()) {
      adj.remove(redirect);
    }
    trace("Removed redirects. Left with %d nodes.", adj.size());

    /*
     * Replace links to redirects with their final destination nodes.
     */
    Collection<Integer> toRemove = new ArrayList<Integer>();
    Collection<Integer> toAdd = new ArrayList<Integer>();
    int nodeCount = 0;
    for (Set<Integer> links : adj.values()) {
      toRemove.clear();
      toAdd.clear();
      for (Integer link : links) {
        Integer redirect = redirects.get(link);
        if (redirect != null) {
          toRemove.add(link);
          toAdd.add(redirect);
        }
      }
      links.removeAll(toRemove);
      links.addAll(toAdd);

      ++nodeCount;
      if (nodeCount % 1000000 == 0)
        trace("Processed %d nodes.", nodeCount);
    }
    trace("Done relinking redirects.");

    AdjWriter writer = new AdjWriter(out);
    writer.write(adj);
    trace("Done writing.");
  }
}
/*
* Copyright (c) 2009 John Lees-Miller
* 
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
* 
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

